home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AMIGA-CD 2
/
Amiga-CD - Volume 2.iso
/
ungepackte_daten
/
1995
/
6
/
02
/
patch-work
/
patchutil.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-01
|
3KB
|
149 lines
/*
** PatchUtil.c von Patrick Ohly
** unterstützende Funktionen für Patches
** © 1994 Patrick Ohly
*/
#include <dos/dosextens.h>
#ifdef _DCC
#include <clib/exec_protos.h>
#else
#include <proto/exec.h>
#endif
#include <exec/memory.h>
#include <exec/execbase.h>
#include "PatchUtil.h"
extern struct ExecBase *SysBase;
/* Werte des Assembler-Befehls JMP */
#define JMP_CMD 0x4EF9
/* Aufbau der Assembler-Sprungbefehle: */
#define JMP 0
#define JMP_ADDR 1 /* ULONG */
/* nur bei alter dos.library verwendet:
** erst D0 auf Funktions-abhängigen Wert setzen,
** dann DOS-dispatcher anspringen
*/
#define MOVEQ 3
#define JMP_DOS 4
#define JMP_DOS_ADDR 5 /* ULONG */
#define BUFFER_SIZE 7
/*
** SafeSetFunction():
** Funktion: änderte einen Library-Vektor auf neue Funktion um
**
** Argumente: library_base - zu patchende Library
** lvo - Offset der zu patchenden Funktion
** new_function - die eigene Funktion
** handle - Zeiger auf Langwort
** Ergebnis: old_function - Zeiger auf alte Funktion oder NULL für Fehler
** handle - wird für RemoveFunction() auf Zeiger
** des Sprungbefehls gesetzt
*/
APTR SafeSetFunction(
struct Library *library_base,
LONG offset,
APTR new_function,
APTR *handle)
{
UWORD *asm_buffer;
APTR result = NULL;
if(asm_buffer = AllocMem(2 * BUFFER_SIZE, MEMF_CLEAR|MEMF_PUBLIC))
{
ULONG current_function;
UWORD *vector;
BOOL standard_lvo;
*handle = asm_buffer;
Disable();
vector = (UWORD *)(((ULONG)library_base) + offset);
/* Standard- und DOS-Format unterstützen */
standard_lvo = (vector[0] == JMP_CMD);
/* JMP- bzw. BRA-Zieladresse ermitteln */
if(standard_lvo)
current_function = *((ULONG *)&vector[1]);
else
current_function = (ULONG)vector +
vector[2] + 4;
/* eigene Funktion in asm_buffer eintragen */
asm_buffer[JMP] = JMP_CMD;
*((APTR *)&asm_buffer[JMP_ADDR]) = new_function;
/* alten Inhalt retten */
if(standard_lvo)
result = (APTR)current_function;
else
{
/* alten DOS-Aufruf nachstellen */
/* moveq #?,d0 */
asm_buffer[MOVEQ] = vector[0];
asm_buffer[JMP_DOS] = JMP_CMD;
*((ULONG *)&asm_buffer[JMP_DOS_ADDR]) =
current_function;
result = &asm_buffer[MOVEQ];
}
/* neuen Zeiger in LVO eintragen */
vector[0] = JMP_CMD;
*((ULONG *)&vector[1]) = (ULONG)asm_buffer;
if(SysBase->LibNode.lib_Version >= 36)
CacheClearU();
/* Library neu berechnen */
library_base->lib_Flags |= LIBF_CHANGED;
SumLibrary(library_base);
Enable();
}
return(result);
}
/*
** RemoveFunction()
** Funktion: macht SafeSetFunction() rückgängig
**
** Argumente: old_function - der Funktionswert, der zurückgeschrieben wird
** handle - der von SafeSetFunction() gesetzte Wert
*/
VOID RemoveFunction(APTR old_function, APTR handle)
{
Disable();
/* alten Wert zurückschreiben */
*((APTR *)&(((UWORD *)handle)[JMP_ADDR])) = old_function;
if(SysBase->LibNode.lib_Version >= 36)
CacheClearU();
Enable();
}
/*
** IsProcess:
** Funktion: testet auf Process
** Ergebnis: TRUE zurück, wenn von einem Prozeß aufgerufen,
** ansonsten FALSE
*/
BOOL IsProcess(VOID)
{
struct Task *my_task;
my_task = FindTask(NULL);
return((BOOL)
(my_task->tc_Node.ln_Type == NT_PROCESS));
}